/*=============================================================================
#     FileName: gserver.h
#         Desc: 
#       Author: Ace
#        Email: goace@acm.org
#     HomePage: http://www.goace.co.cc
#      Version: 0.0.1
#   LastChange: 2011-05-11 22:59:45
#      History:
=============================================================================*/
#ifndef GSERVER_H_
#define GSERVER_H_

#define DEBUG

#include	<stdint.h>
#include	<sys/types.h>
#include	<string>
#include	<vector>
#include	<queue>
using std::string;
using std::vector;
using std::queue;

//system limits
#define		USR_LEN			128	    //最大用户名长度
#define		PWD_LEN			128     //最大密码长度
#define		PATH_LEN		256		//最大路径长度
#define		FILE_LEN		32		//最长文件名
#define		BUF_SIZE		1024
#define		BLOCK_SIZE		4096	//文件传输的块大小

//data进程中的状态机
#define		DATA_INIT			1
#define		DATA_SYNC			2
#define		DATA_PUSH			3
#define		DATA_PULL			4
#define     DATA_LIST			5

#define     WAIT_ID				1
#define     WAIT_PATH			2
#define     WAIT_ACK			3
#define     SENDING				4
#define     RECEIVING			5
#define     WAIT_PEER			6
#define     WAIT_REAL			7

#define		SYNC_WAIT_ID		WAIT_ID
#define		SYNC_WAIT_PEER		WAIT_PEER
#define		SYNC_WAIT_REAL		WAIT_REAL
#define		SYNC_SENDING		SENDING

#define		PUSH_WAIT_ID		WAIT_ID
#define		PUSH_WAIT_PATH		WAIT_PATH
#define		PUSH_WAIT_ACK		WAIT_ACK
#define		PUSH_SENDING		SENDING
#define		PUSH_RECIVING		RECEIVING

#define		PULL_WAIT_ID		WAIT_ID
#define		PULL_WAIT_PATH		WAIT_PATH
#define		PULL_RECIVING		RECEVING
#define		PULL_WAIT_ACK		WAIT_ACK
#define		PULL_SENDING		SENDING


//about epoll
#define		EPOLL_MAX_FD		5000
#define		EPOLL_MAX_EVENTS	10

//端口
#define		SRV_DATA_PORT		"1235"
#define		SRV_CTL_PORT		"1234"
#define     SRV_NOTIFY_PORT		"1236"

//通信协议
#define		REG					1		//注册
#define		LOGIN				2		//登录
#define		CREATE_D			3		//新建目录
#define		CREATE_F			4		//创建文件
#define		DEL_F				5		//删除文件
#define		DEL_D				6		//删除目录
#define		UP_F				7		//更新文件
#define		UP_D				8		//更新目录
#define		EXIT				9		//用户退出
#define		MOVE				10		//移动文件、目录
#define     LOGIN_PHONE			11		//手机端登录
#define     REQUEST_LIST		12		//手机请求目录

//信号量
#define QUEUE_N				0
#define MUTEX				1

//信号量的KEY
#define SEM_KEY				1026

#define SA struct sockaddr

//服务器上的根目录
#define SRV_ROOT "/gsync"


/* ---------------------------------------------------------------*/
/**
 * 简介: 以下4个结构体是与ctl进程相关的  
 */
/* ---------------------------------------------------------------*/
typedef struct id_pair
{
	char		usr[USR_LEN]; //用户名
	char		pwd[PWD_LEN]; //密码
} id_pair_t;

typedef union str
{
	id_pair_t	id;
	char		path[PATH_LEN];
} str_t;

/*控制信息的连接中传的包*/
typedef struct ctl_pkg
{
	uint8_t		type;  
	str_t		str;	
} ctl_pkg_t;

/* 
 * 记录一个目录里面的成员的结构体
 * 用于返回给手机端
 * type：0表示结束
 *		 1表示文件
 *		 2表示目录	
*/
typedef struct item_info
{
	uint8_t				type;
	char				name[FILE_LEN];
} item_info_t;


/* 控制连接中每个连接的状态,
 * 记录在events.data.ptr中*/
typedef struct ctl_sock_info
{
	int32_t				fd;
	int32_t				notify_fd;
	int32_t				version;
	bool				updated;
	int8_t				state;
	int8_t				reply;
	vector<ctl_pkg_t*>	history;
	vector<item_info*>	items;
	char				usr_name[USR_LEN];
	struct sockaddr		peer_addr;
} ctl_sock_info_t;


/* 数据连接中每个连接的状态，
 * 记录在events.data.ptr中*/
typedef struct data_sock_info
{
	int32_t				p[2];
	int32_t				sock_fd;
	int32_t				file_fd;
	ssize_t				total;			//传输中文件的总字节数
	ssize_t				tsfd;			//已传输的字节数
	uint32_t			peer_version;	//对方的版本
	uint32_t			real_version;	//服务器版本号
	uint8_t				type;			//INIT SYNC  PUSH  PULL
	int8_t				state;
	char				usr_name[USR_LEN];
	bool				transfering;

} data_sock_info_t;


struct update_head
{
	uint8_t type;
	char usr[USR_LEN];
	char pwd[PWD_LEN];
	char path[PATH_LEN];
};

//函数声明
int init_semvalue(int sem_id, int sem_num);
int sem_wait(int sem_id, int sem_num);
int sem_signal(int sem_id, int sem_num);
ssize_t writen(int fd, const void *vptr, size_t n);
void Writen(int fd, void *ptr, size_t nbytes);
ssize_t readn(int fd, void *vptr, size_t n);
void file_rcv(int det, int src);
void file_copy(int det, int src);
void get_home(string& dir);
void* process_thread(void* gsyncer);
void dir_search(vector<string>& watch_list, string& pre_path);
void usr_exit(ctl_sock_info_t* info);
#endif
